package main

import (
	"fmt"
	"net"
)

//Server -- 镜像端
type Server struct {
	cons             map[int]net.Conn
	ChannelAddress   *net.TCPAddr
	MirroringAddress *net.TCPAddr
}

func NewServer(channelAddress *net.TCPAddr, mirroringAddress *net.TCPAddr) *Server {
	return &Server{cons: make(map[int]net.Conn), ChannelAddress: channelAddress, MirroringAddress: mirroringAddress}
}

func (s *Server) Start() {

	send, receive := ChannelHandler(s.ChannelAddress)
	go s.channelReceive(send, receive)

	lis, err := net.ListenTCP("tcp", s.MirroringAddress)
	if err != nil {
		panic(fmt.Sprintf("监听端口失败:%v", err))
	}

	//go func() {
	for i := 0; ; i++ {
		if con, err := lis.Accept(); err == nil {
			usrid := i
			s.cons[usrid] = con
			cmdnew := NewPacket(CMDNEW, uint32(usrid))
			send <- cmdnew
			<-cmdnew.done

			fmt.Printf("用户(%v)连接成功\n", i)

			go s.userReceive(con, usrid, send)
		}
	}
	//}()
}

func (s *Server) channelReceive(send, receive chan *packet) {
	for {
		select {
		case r := <-receive:
			cmd := r.Cmd()

			if cmd == CMDPACKET {
				cid := r.Usrid()
				fmt.Print("*")
				c, exist := s.cons[cid]
				if exist {
					if _, err := c.Write(r.Payload()); err != nil {
						fmt.Println(err)

						cls := NewPacket(CMDCLOSE, uint32(cid))
						send <- cls
						<-cls.done

						delete(s.cons, cid)
						c.Close()
					}
				}
			} else if cmd == CMDCLOSE {
				usrid := r.Usrid()
				fmt.Printf("关闭用户命令(%v).\n", usrid)
				if c, exist := s.cons[usrid]; exist {
					delete(s.cons, usrid)
					c.Close()
				}
			} else {
				panic("未知的命令")
			}

			r.done <- true
		}
	}
}

func (s *Server) userReceive(con net.Conn, usrid int, send chan *packet) {
	p := NewPacket(CMDPACKET, uint32(usrid))
	for {

		p.ResetPayload()
		Payload := p.Payload()
		tmp := Payload[:cap(Payload)]
		n, err := con.Read(tmp)
		p.AllocPayload(uint32(n))

		if _, ok := s.cons[usrid]; !ok {
			break
		}

		if n > 0 {
			send <- p
			<-p.done
		}

		if err != nil {
			fmt.Printf("用户连接关闭(%v).\n", usrid)
			con.Close()
			delete(s.cons, usrid)

			cls := NewPacket(CMDCLOSE, uint32(usrid))
			send <- cls
			<-cls.done

			break
		}
	}
}

func ChannelHandler(address *net.TCPAddr) (send, receive chan *packet) {
	send = make(chan *packet)
	receive = make(chan *packet)

	lis, err := net.ListenTCP("tcp", address)
	if err != nil {
		panic(fmt.Sprintf("监听端口失败:%v", err))
	}

	go func() {
		for {
			if con, err2 := lis.Accept(); err2 == nil {
				fmt.Println("-通道已连接-")
				go func() {
					defer fmt.Println("通道已断开")

					stop := make(chan bool)
					go packetSend(con, send, stop)

					packetReceive(con, receive)
					close(stop)
				}()
			} else {
				fmt.Println(err2)
			}
		}
	}()
	return
}
